package cn.calm.xhtml.processor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import cn.calm.xhtml.annotation.Attribute;
import cn.calm.xhtml.annotation.Tag;

/**
 * 标签处理
 * @author dingqihui
 *
 */
@SupportedAnnotationTypes(value = { "cn.calm.xhtml.annotation.Tag" })
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class TagProcessor extends AbstractProcessor {
	public static final String NAMESPACE="http://www.calm.cn/extras/tag";
	public static final String XML_DIR = "src/main/resources/META-INF/namespace";
	private Map<String,XmlDocument> namespaces =new HashMap<>();
//	@Override 
//	public void init(ProcessingEnvironment env) {
//	}

	/* (non-Javadoc)
	 * @see javax.annotation.processing.AbstractProcessor#process(java.util.Set, javax.annotation.processing.RoundEnvironment)
	 */
	@Override
	public boolean process(Set<? extends TypeElement> annotations,
			RoundEnvironment roundEnv) {

		for (javax.lang.model.element.Element e : roundEnv.getRootElements()) {
			Tag tag = e.getAnnotation(Tag.class);
			if (tag == null) {
				continue;
			}
			String namespace = tag.namespace();
			String tempSpace;
			if (namespace.endsWith("/")) {
				tempSpace = namespace.substring(0, namespace.length() - 1);
			} else {
				tempSpace = namespace;
			}
			
			int lastIndexOf = tempSpace.lastIndexOf("/");
			String fileName = tempSpace.substring(lastIndexOf + 1);
			File dir = new File(XML_DIR);
			if (!dir.isDirectory()) {
				dir.mkdirs();
			}
			File xmlFile = new File(dir, fileName + ".xml");
			XmlDocument xd;
			if(namespaces.containsKey(tempSpace)){
				xd = namespaces.get(tempSpace);
			}else{
				if(xmlFile.isFile()){
					xmlFile.delete();
				}
				
				Document document  = DocumentHelper.createDocument();
				Element root = DocumentHelper.createElement("namespace");
				document.setRootElement(root);
				
				Namespace ns=Namespace.get(NAMESPACE); 
				root.add(ns);
				
				ns=Namespace.get("xsi","http://www.w3.org/2001/XMLSchema-instance"); 
				root.add(ns);
				root.addAttribute("xsi:schemaLocation", NAMESPACE+" "+NAMESPACE);
				root.addAttribute("uri", tempSpace);
				
				xd=new XmlDocument(document,root,xmlFile);
				
				namespaces.put(tempSpace, xd);
			}
			
			processTag(xd,tag,e);
			for(Map.Entry<String,XmlDocument> en:namespaces.entrySet()){
				OutputFormat format = new OutputFormat();// 设置缩进为4个空格，并且另起一行为true
				format.setIndent(true); 
				format.setNewlines(true);
				format.setEncoding("UTF-8");
				XMLWriter xmlWriter2;
				XmlDocument value = en.getValue();
				try {
					xmlWriter2 = new XMLWriter(new FileOutputStream(value.getFile()), format);
					xmlWriter2.write(value.getDocument());
				} catch (UnsupportedEncodingException e1) {
					e1.printStackTrace();
				} catch (FileNotFoundException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				
			}
			
		}
		return true;
	}
	/**
	 * @param xd
	 * @param tag
	 * @param e
	 */
	private void processTag(XmlDocument xd,Tag tag,javax.lang.model.element.Element e){
		
		Element root=xd.getRoot();
		Element node = root.addElement("tag",NAMESPACE);
		
		String name = tag.name();
		if(StringUtils.isBlank(name)){
			String string = e.getSimpleName().toString();
			name=string.substring(0,1).toLowerCase()+string.substring(1);
		}
		node.addAttribute("name", name);
		String className = e.toString();
		node.addAttribute("className" ,className);
		
		boolean hasContent = tag.hasContent();
		if(!hasContent){
			node.addAttribute("hasContent", "false");
		}
		String description = tag.description();
		if(StringUtils.isNotBlank(description)){
			Element desc = node.addElement("desc",NAMESPACE);
			desc.addCDATA(description);
		}
		
		processAttr(tag, node);
		
	}
	private void processAttr(Tag tag, Element node) {
		Attribute[] attributes = tag.attributes();
		for(Attribute attr:attributes){
			Element attrElem = node.addElement("attr",NAMESPACE);
			String description = attr.description();
			if(StringUtils.isNotBlank(description)){
				Element desc = attrElem.addElement("desc",NAMESPACE);
				desc.addCDATA(description);
			}
			String name2 = attr.name();
			attrElem.addAttribute("name", name2);
			boolean require = attr.require();
			if(require){
				attrElem.addAttribute("require", "true");
			}
			String template = attr.template();
			if(StringUtils.isNotBlank(template)){
				Element desc = attrElem.addElement("template",NAMESPACE);
				desc.addCDATA(template);
			}
		}
	}
}
